﻿using System.Collections.Concurrent;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.Config;
using WeDonekRpc.PipeClient.Model;
using WeDonekRpc.PipeClient.SystemAllot;
namespace WeDonekRpc.PipeClient.Config
{
    public class PipeConfig
    {
        private static readonly IConfigSection _Config;

        private static readonly int _DefHeartBeat = Tools.GetRandom(60000, 110000);
        private static readonly string _ServerKey;

        static PipeConfig ()
        {
            _Config = LocalConfig.Local.GetSection("pipe:Client");
            ServerName = _Config.GetValue("ServerName", ".");
            PipeName = _Config.GetValue("PipeName");
            _ServerKey = _Config.GetValue("ServerKey", "6xy3#7a%ad").GetMd5();
            _Config.AddRefreshEvent(_Refresh);
        }

        private static void _Refresh (IConfigSection section, string name)
        {
            IsSyncRead = section.GetValue<bool>("IsSyncRead", false);
            HeartbeatTime = section.GetValue<int>("Heartbeat", _DefHeartBeat);
            SyncTimeOut = section.GetValue("SyncTimeOut", 12000);
            SpinWait = section.GetValue<int>("SpinWait", 0);
            Timeout = section.GetValue<int>("TimeOut", 10);
            ConTimeout = section.GetValue<int>("ConTimeout", 5000);
            ClientNum = section.GetValue<int>("ClientNum", 2);
            UpFileMD5LimitSize = section.GetValue<int>("UpFileMD5LimitSize", 5 * 1024 * 1024);
            UpFileSendTimeOut = section.GetValue<int>("UpFileSendTimeOut", 10);
            BufferSize = section.GetValue<int>("BufferSize", 8192);
        }
        public static int BufferSize { get; private set; } = 8192;

        private static Interface.ISocketEvent _SocketEvent = null;


        public static Interface.ISocketEvent SocketEvent
        {
            get => PipeConfig._SocketEvent;
            set => PipeConfig._SocketEvent = value;
        }

        private static Interface.IAllot _Allot = new ReplyAllot();

        /// <summary>
        /// 用于接收服务端的广播
        /// </summary>
        public static Interface.IAllot Allot
        {
            get => (Interface.IAllot)PipeConfig._Allot.Clone();
            set => PipeConfig._Allot = value;
        }

        /// <summary>
        /// 服务器名
        /// </summary>
        public static string ServerName
        {
            get;
            private set;
        } = ".";


        /// <summary>
        /// 隧道名称
        /// </summary>
        public static string PipeName
        {
            get;
            private set;
        }

        /// <summary>
        /// 同步等待时间(毫秒)
        /// </summary>
        public static int SpinWait
        {
            get;
            private set;
        } = 0;
        public static bool IsSyncRead
        {
            get;
            private set;
        }
        private static readonly ConcurrentDictionary<string, ServerConConfig> _ServerConnectArg = new ConcurrentDictionary<string, ServerConConfig>();

        public void SetConArg (string host, string pipeName, string publicKey, params string[] arg)
        {
            AddConArg(host, pipeName, publicKey, arg);
        }
        public void SetConArg (string host, string pipeName, params string[] arg)
        {
            AddConArg(host, pipeName, arg);
        }
        public static void AddConArg (string host, string pipeName, params string[] arg)
        {
            AddConArg(host, pipeName, null, arg);
        }


        public static void AddConArg (string host, string pipeName, string publicKey, params string[] arg)
        {
            if (arg == null)
            {
                arg = System.Array.Empty<string>();
            }
            string key = string.Format("{0}:{1}", host, pipeName);
            publicKey = publicKey == null ? _ServerKey : Tools.GetMD5(publicKey);
            if (_ServerConnectArg.TryGetValue(key, out ServerConConfig config))
            {
                config.Arg = arg;
                config.ConKey = publicKey;
            }
            else
            {
                _ = _ServerConnectArg.TryAdd(key, new ServerConConfig(publicKey, arg));
            }
        }
        internal static ServerConConfig GetConArg (string serverId)
        {
            return _ServerConnectArg.TryGetValue(serverId, out ServerConConfig config) ? config : new ServerConConfig(_ServerKey, null);
        }

        /// <summary>
        /// 心跳间隔时间
        /// </summary>
        public static int HeartbeatTime
        {
            get;
            private set;
        } = 60000;

        /// <summary>
        /// 发送超时时间（秒）
        /// </summary>
        public static int Timeout
        {
            get;
            private set;
        }
        /// <summary>
        /// 命名管道链接超时
        /// </summary>
        public static int ConTimeout
        {
            get;
            private set;
        } = 5000;
        /// <summary>
        /// 同步超时时间
        /// </summary>
        public static int SyncTimeOut { get; private set; } = 12000;
        /// <summary>
        /// 连接池最小链接数
        /// </summary>
        public static int ClientNum { get; private set; } = 2;
        /// <summary>
        /// 上传文件计算MD5最大大小
        /// </summary>
        public static int UpFileMD5LimitSize { get; private set; } = 5 * 1024 * 1024;
        /// <summary>
        /// 文件上传发送超时时间
        /// </summary>
        public static int UpFileSendTimeOut { get; private set; } = 10;

    }
}
